package com.hfb.mashibing.alip8.designpattern._12proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * Q：现有如下代码，问题：我想记录坦克的移动时间，该怎么做？
 * A：修改源码，做时间记录 V2
 * Q：那如果无法修改源码的情况下，如何实现呢？V3
 * A：用继承,继承他的实现类 V4
 * Q：应该用代理吧 V5 (持有代理对象实现类的引用，并实现代理接口)
 * Q：V6 代理有各种类型，如何实现代理的各种组合？继承？组合？
 * Q: V7 代理对象改为接口 (持有代理对象实现类的接口的引用，并实现该接口)
 * Q: V8 如果想让LogProxy 可以重用，不仅可以代理日志，
 * 还可以代理其他可以代理的类型 Object
 * （毕竟日志记录，时间计算是喝多系统都用到的东西）这个时候该怎么做呢？
 * A: 分离代理行为与被代理对象——使用jdk动态代理
 */

public class V8Tank implements MovableV8 {
    public static void main(String[] args) {
        V8Tank tank = new V8Tank();
        // reflection:通过二进制字节码分析类的属性和方法
        MovableV8 m = (MovableV8) Proxy.newProxyInstance(tank.getClass().getClassLoader(),
            new Class[]{MovableV8.class}, // tank.getClass().getInterfaces()
            new LogTankV8(tank));
        m.move();
    }


    @Override
    public void move() {
        System.out.println("V8 tank is moving.......");
        try {
            TimeUnit.SECONDS.sleep(new Random().nextInt(5));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("V8 tank is move end......");
    }

}
class LogTankV8 implements InvocationHandler{

    private V8Tank tank;

    public LogTankV8(V8Tank tank) {
        this.tank = tank;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("method "+method.getName()+ Arrays.toString(args));
        Object o = method.invoke(tank, args);
        System.out.println("method "+method.getName()+ Objects.toString(o));
        return o;
    }
}


interface MovableV8 {
    void move();
}
